//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.liy.supercloud.server.gateway.filter;

import com.liy.framework.common.extvo.TokenVo;
import com.liy.framework.common.redis.utils.RedisKeyUtils;
import com.liy.framework.common.redis.utils.RedisUtils;
import com.liy.supercloud.server.gateway.task.GatewayCountTimer;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;

import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UrlPathHelper;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class MyGlobalFilter implements GlobalFilter, Ordered {
    Logger logger = LoggerFactory.getLogger(MyGlobalFilter.class);
    public static final String START_TIME = "startTime";
    @Autowired
    private RedisUtils redisUtils;
    @Value("${dascloud.authrization.token.expire:1800000}")
    private long expire;
    @Value("${dascloud.authrization.token.refresh: 300000}")
    private long refresh;
    @Value("${dascloud.authrization.enabled: true}")
    private Boolean authrizationEnabled;
    @Value("${dascloud.permission.enabled: true}")
    private Boolean permissionEnabled;
    @Value("${dascloud.authrization.token-header: JwtToken}")
    private String tokenName;
    @Value("${dascloud.authrization.auth-key: AuthKey}")
    private String authKeyName;
    private static String[] excludesUrlArray = null;
    private static UrlPathHelper pathHelper = new UrlPathHelper();
    private static PathMatcher pathMatcher = new AntPathMatcher();

    public MyGlobalFilter() {
    }

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        GatewayCountTimer.getNextRequestTotalNumber();
        ServerHttpRequest request = exchange.getRequest();
        String info = String.format("Gateway -> Method:{%s} Host:{%s} Path:{%s} Query:{%s}", request.getMethod().name(), request.getURI().getHost(), request.getURI().getPath(), request.getQueryParams());
        this.logger.info(info);
        String authKey = this.extractAuthorization(request);
        ServerWebExchange swe = exchange;
        if (authKey != null && !authKey.isEmpty()) {
            try {
                this.logger.info("authKey:" + authKey);
                String tokenId = RedisKeyUtils.base642tokenId(authKey);
                if (tokenId == null) {
                    return this.handlerError(exchange, "401", "认证码错误.");
                }

                TokenVo tokenVo = (TokenVo)this.redisUtils.get(tokenId);
                if (tokenVo == null) {
                    exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                    return this.handlerError(exchange, "401", "认证码信息已过期，请重新登录获取.");
                }

                if (tokenVo.getStatus() != 0) {
                    exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                    return this.handlerError(exchange, "403", "对不起，该用户已被禁止访问，请联系管理员.");
                }

                if (System.currentTimeMillis() - tokenVo.getLastOperationTime() > this.refresh) {
                    tokenVo.setLastOperationTime(System.currentTimeMillis());
                    this.redisUtils.set(tokenId, tokenVo, this.expire);
                    this.logger.info("Service gateway token refreshed, expire=" + this.expire);
                }

                ServerHttpRequest requestNew = exchange.getRequest().mutate().header("AuthKey", authKey).header(this.tokenName, tokenVo.getJwt()).build();
                swe = exchange.mutate().request(requestNew).build();
            } catch (UnsupportedEncodingException var10) {
                return this.handlerError(exchange, "500", "认证码解析错误：" + var10.getMessage());
            }
        }

        exchange.getAttributes().put("startTime", System.currentTimeMillis());
        return chain.filter(swe).then(Mono.fromRunnable(() -> {
            GatewayCountTimer.getNextRequestSuccessNumber();
            Long startTime = (Long)exchange.getAttribute("startTime");
            if (startTime != null) {
                Long executeTime = System.currentTimeMillis() - startTime;
                GatewayCountTimer.setResponseMaxTimer(executeTime);
                this.logger.info(request.getURI().getRawPath() + " : " + executeTime + "ms");
            }

        }));
    }

    private Mono<Void> handlerError(ServerWebExchange exchange, String status, String message) {
        GatewayCountTimer.getNextRequestFailureNumber();
        String msg = "{\"status\":\"" + status + "\",\"message\":\"" + message + "\",\"success\":false,\"timestamp\": \"" + System.currentTimeMillis() + "\"}";
        byte[] bytes = msg.getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
        return exchange.getResponse().writeWith(Flux.just(buffer));
    }

    private ServerHttpResponseDecorator handlerResponse(ServerWebExchange exchange) {
        ServerHttpResponse originalResponse = exchange.getResponse();
        final DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = (Flux)body;
                    return super.writeWith(fluxBody.map((dataBuffer) -> {
                        byte[] content = new byte[dataBuffer.readableByteCount()];
                        dataBuffer.read(content);
                        DataBufferUtils.release(dataBuffer);
                        new String(content, Charset.forName("UTF-8"));
                        byte[] uppedContent = (new String(content, Charset.forName("UTF-8"))).getBytes();
                        return bufferFactory.wrap(uppedContent);
                    }));
                } else {
                    return super.writeWith(body);
                }
            }
        };
        return decoratedResponse;
    }

    private String extractAuthorization(ServerHttpRequest request) {
        List<String> headers = request.getHeaders().get(this.authKeyName);
        if (Objects.nonNull(headers) && headers.size() > 0) {
            String value = (String)headers.get(0);
            return value;
        } else {
            return null;
        }
    }

    public int getOrder() {
        return -100;
    }
}
